package io.github.uicdb.badskill.api;

import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import io.github.uicdb.badskill.BadSkill;
import io.github.uicdb.badskill.PlayerSkillCapabilityProvider;
import io.github.uicdb.badskill.SkillOption;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.EntityArgument;
import net.minecraft.commands.arguments.coordinates.BlockPosArgument;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.AABB;
import net.minecraftforge.event.RegisterCommandsEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE, modid = BadSkill.MODID)
public class BSCommands {
    @SubscribeEvent
    public static void register(RegisterCommandsEvent event) {
        register(event.getDispatcher());
    }

    private static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
        dispatcher.register(Commands.literal("badskill").requires((stack) -> stack.hasPermission(2))
                .then(Commands.literal("learn").then(Commands.argument("target", EntityArgument.player()).then(Commands.argument("option", OptionArgType.option()).executes(context -> {
                    SkillOption option = OptionArgType.getOption(context, "option");
                    ServerPlayer player = EntityArgument.getPlayer(context, "target");
                    if (option != null)
                        player.getCapability(PlayerSkillCapabilityProvider.CAPABILITY)
                                .ifPresent(capability -> capability.forceLearn(option));
                    return 1;
                }))))
                .then(Commands.literal("retreated").then(Commands.argument("target", EntityArgument.player()).then(Commands.argument("option", OptionArgType.option()).executes(context -> {
                    SkillOption option = OptionArgType.getOption(context, "option");
                    ServerPlayer player = EntityArgument.getPlayer(context, "target");
                    if (option != null)
                        player.getCapability(PlayerSkillCapabilityProvider.CAPABILITY)
                                .ifPresent(capability -> capability.retreated(option,false));
                    return 1;
                }))))
                .then(Commands.literal("disable").then(Commands.argument("from", BlockPosArgument.blockPos()).then(Commands.argument("to", BlockPosArgument.blockPos()).then(Commands.argument("ticks", IntegerArgumentType.integer(1)).executes(context1 -> {
                    BlockPos from = BlockPosArgument.getBlockPos(context1, "from");
                    BlockPos to = BlockPosArgument.getBlockPos(context1, "to");
                    AABB aabb = new AABB(from, to);
                    int ticks = IntegerArgumentType.getInteger(context1, "ticks");
                    context1.getSource().getServer()
                            .getPlayerList().getPlayers()
                            .stream()
                            .filter(serverPlayer -> aabb.contains(serverPlayer.position()))
                            .forEach(serverPlayer -> serverPlayer.getCapability(PlayerSkillCapabilityProvider.CAPABILITY)
                                    .ifPresent(capability -> {
                                        capability.disableAll(ticks);
                                    }));
                    return 1;
                })))))
        );
    }
}
